package com.weaver.controller;

import com.weaver.model.Model;
import com.weaver.view.View;

import javax.swing.JButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

/**
 * Controller class - Handles user input and updates the model
 */
public class Controller implements ActionListener {
    private Model model;
    private View view;
    
    private StringBuilder currentInput;
    private static final int WORD_LENGTH = 4;
    
    /**
     * Constructor
     * @param model game model
     */
    public Controller(Model model) {
        this.model = model;
        this.currentInput = new StringBuilder();
    }
    
    /**
     * Set the view
     * @param view game view
     */
    public void setView(View view) {
        this.view = view;
    }
    
    /**
     * Handle key input
     * @param key key character
     */
    public void handleKeyInput(char key) {
        // If game is already won, ignore input
        if (model.isGameWon()) {
            return;
        }
        
        // Convert to uppercase
        key = Character.toUpperCase(key);
        
        // Only process letters
        if (key >= 'A' && key <= 'Z') {
            // If current input length is less than word length, add character
            if (currentInput.length() < WORD_LENGTH) {
                currentInput.append(key);
                updateView();
            }
        }
        // Handle backspace key
        else if (key == '\b') {
            handleBackspace();
        }
        // Handle enter key
        else if (key == '\n') {
            handleEnter();
        }
    }
    
    /**
     * Handle backspace key
     */
    public void handleBackspace() {
        // If current input is not empty, delete the last character
        if (currentInput.length() > 0) {
            currentInput.deleteCharAt(currentInput.length() - 1);
            updateView();
        }
    }
    
    /**
     * Handle enter key
     */
    public void handleEnter() {
        // If current input length equals word length, try to submit
        if (currentInput.length() == WORD_LENGTH) {
            String word = currentInput.toString();
            boolean success = model.tryWord(word);
            
            if (success) {
                // Clear current input
                currentInput.setLength(0);
                // Update view with success flag (false means no error)
                model.notifyChange(Boolean.FALSE);
            } else {
                if (view != null && model.isShowErrorMessage()) {
                    // Show error message on status label
                    view.showError("'" + word + "' is not a valid word or doesn't follow the rules");
                    
                    // Update view with error flag (true means error)
                    model.notifyChange(Boolean.TRUE);
                    
                    // Schedule a reset of the error state after 1 second
                    new javax.swing.Timer(1000, e -> {
                        // Clear current input
                        currentInput.setLength(0);
                        // Update view with normal state
                        model.notifyChange(currentInput.toString());
                        ((javax.swing.Timer)e.getSource()).stop();
                    }).start();
                } else {
                    // Clear current input even if the word is invalid
                    currentInput.setLength(0);
                    model.notifyChange(currentInput.toString());
                }
            }
        }
    }
    
    /**
     * Update the view
     */
    private void updateView() {
        // Notify model that state has changed with current input
        model.notifyChange(currentInput.toString());
    }
    
    /**
     * Reset the game
     */
    public void resetGame() {
        // Clear current input
        currentInput.setLength(0);
        
        // Initialize game
        model.initGame();
    }
    
    /**
     * New game
     */
    public void newGame() {
        // Clear current input
        currentInput.setLength(0);
        
        // Initialize game
        model.initGame();
    }
    
    /**
     * Get keyboard adapter
     * @return keyboard adapter
     */
    public KeyAdapter getKeyAdapter() {
        return new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                handleKeyInput(e.getKeyChar());
            }
        };
    }
    
    /**
     * Handle action events
     * @param e action event
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        
        switch (command) {
            case "LETTER":
                // Handle letter button
                JButton button = (JButton) e.getSource();
                String letter = button.getText();
                if (letter.length() == 1) {
                    handleKeyInput(letter.charAt(0));
                }
                break;
            case "BACKSPACE":
                // Handle backspace button
                handleBackspace();
                break;
            case "ENTER":
                // Handle enter button
                handleEnter();
                break;
            case "RESTART":
                // Handle reset button
                resetGame();
                break;
            case "RUN":
                // Handle new game button
                newGame();
                break;
            case "TOGGLE_ERROR_MESSAGE":
                // Toggle error message flag
                model.setShowErrorMessage(!model.isShowErrorMessage());
                break;
            case "TOGGLE_SHOW_PATH":
                // Toggle show path flag
                model.setShowPath(!model.isShowPath());
                break;
            case "TOGGLE_RANDOM_WORDS":
                // Toggle random words flag
                model.setUseRandomWords(!model.isUseRandomWords());
                break;
        }
    }
    
    /**
     * Get current input
     * @return current input
     */
    public String getCurrentInput() {
        return currentInput.toString();
    }
}